﻿-----------------------------------------------------------------------------------------------
------------------------------ Funciones pca_almacen.almacenes --------------------------------
-----------------------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION pca_almacen.fn_add_almacen(varchar,--almacen $1
						      varchar,--ubicacion $2
						      varchar,--oficina_id $3
						      varchar --empresa_id $4
						      )RETURNS void AS
$$
BEGIN
	$1 := initcap(trim(both ' ' from $1));
	$2 := initcap(trim(both ' ' from $2));

	IF NOT EXISTS(
		SELECT
			almacen
		FROM
			pca_almacen.almacenes
		WHERE
			almacen=$1 AND
			ubicacion=$2 AND
			oficina_id=$3 AND
			empresa_id=$4
	)THEN
		INSERT INTO pca_almacen.almacenes
			(almacen,
			ubicacion,
			oficina_id,
			empresa_id)
		VALUES
			($1,$2,$3,$4);
	END IF;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_update_almacen(varchar,--almacen OLD $1
							 varchar,--oficina_id $2
							 varchar,--empresa_id $3
							 varchar --almacen NEW $4
							 )RETURNS void AS
$$
BEGIN
	$4 := initcap(trim(both ' ' from $4));

	UPDATE
		pca_almacen.almacenes
	SET
		almacen = $4
	WHERE
		almacen = $1 AND
		oficina_id = $2 AND
		empresa_id = $3;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_update_ubicacion(varchar,--almacen $1
							   varchar,--ubicacion OLD $2
							   varchar,--oficina_id $3
							   varchar,--empresa_id $4
							   varchar --ubicacion NEW $5
							   )RETURNS void AS
$$
BEGIN
	$1 := trim(both ' ' from $1);
	$2 := trim(both ' ' from $2);
	$5 := initcap(trim(both ' ' from $5));

	IF NOT EXISTS (--buscamos que no exista almacen-ubicacion con la nueva informacion
		SELECT
			almacen
		FROM
			pca_almacen.almacenes
		WHERE
			oficina_id=$3 AND
			empresa_id=$4 AND
			almacen=$1 AND
			ubicacion=$5
	)THEN
		UPDATE pca_almacen.almacenes SET
			ubicacion=$5
		WHERE
			almacen=$1 AND
			ubicacion=$2 AND
			oficina_id=$3 AND
			empresa_id=$4;
	ELSE
		IF($2<>$5)THEN
			RAISE EXCEPTION 'Ya existe un almacen : %, Ubicacion : %',$1,$5;
		END IF;
	END IF;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_del_almacen(varchar,--almacen $1
						      varchar,--oficina_id $2
						      varchar --empresa_id $3
						      )RETURNS void AS
$$
BEGIN
	DELETE FROM
		pca_almacen.almacenes
	WHERE
		almacen = $1 AND
		oficina_id = $2 AND
		empresa_id = $3;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_del_almacen(varchar,--almacen $1
						      varchar,--ubicacion $2
						      varchar,--oficina_id $3
						      varchar --empresa_id $4
						      )RETURNS void AS
$$
BEGIN
	DELETE FROM
		pca_almacen.almacenes
	WHERE
		almacen = $1 AND
		ubicacion = $2 AND
		oficina_id = $3 AND
		empresa_id = $4;
END;
$$
LANGUAGE plpgsql;

--Devuelve una lista de todos los almacenes existente en una determinada oficina
CREATE OR REPLACE FUNCTION pca_almacen.fn_get_list_almacenes(varchar,--oficina_id $1
							     varchar --empresa_id $2
							     )RETURNS SETOF pca_almacen.almacenes AS
$$
DECLARE
	_row pca_almacen.almacenes%ROWTYPE;
BEGIN
	FOR _row IN
		SELECT DISTINCT ON(almacen)
			almacen,
			ubicacion,
			oficina_id,
			empresa_id
		FROM
			pca_almacen.almacenes
		WHERE
			oficina_id = $1 AND
			empresa_id = $2
		ORDER BY
			almacen ASC,
			ubicacion ASC
	LOOP
		RETURN NEXT _row;
	END LOOP;
END;
$$
LANGUAGE plpgsql;

--Devuelve una lista filtrada de todos los almacenes existente en una determinada oficina
CREATE OR REPLACE FUNCTION pca_almacen.fn_get_list_almacenes(varchar,--oficina_id $1
							     varchar,--empresa_id $2
							     varchar --almacen $3
							     )RETURNS SETOF pca_almacen.almacenes AS
$$
DECLARE
	_row pca_almacen.almacenes%ROWTYPE;
BEGIN
	FOR _row IN
		SELECT DISTINCT ON(almacen)
			almacen,
			ubicacion,
			oficina_id,
			empresa_id
		FROM
			pca_almacen.almacenes
		WHERE
			oficina_id = $1 AND
			empresa_id = $2 AND
			lower(pca_global.fn_ascii(almacen)) LIKE '%'|| lower(pca_global.fn_ascii($3)) ||'%'
		ORDER BY
			almacen ASC,
			ubicacion ASC
	LOOP
		RETURN NEXT _row;
	END LOOP;
END;
$$
LANGUAGE plpgsql;

--Devuelve una lista de todos las ubicaciones que pertenecen a un determinado almacen
CREATE OR REPLACE FUNCTION pca_almacen.fn_get_list_ubicaciones(varchar,--oficina_id $1
							       varchar,--empresa_id $2
							       varchar --almacen $3
							       )RETURNS SETOF pca_almacen.almacenes AS
$$
DECLARE
	_row pca_almacen.almacenes%ROWTYPE;
BEGIN
	FOR _row IN
		SELECT
			almacen,
			ubicacion,
			oficina_id,
			empresa_id
		FROM
			pca_almacen.almacenes
		WHERE
			oficina_id = $1 AND
			empresa_id = $2 AND
			lower(pca_global.fn_ascii(almacen)) = lower(pca_global.fn_ascii($3))
		ORDER BY
			almacen ASC,
			ubicacion ASC
	LOOP
		RETURN NEXT _row;
	END LOOP;
END;
$$
LANGUAGE plpgsql;

--Devuelve una lista filtrada de todos las ubicaciones que pertenecen a un determinado almacen
CREATE OR REPLACE FUNCTION pca_almacen.fn_get_list_ubicaciones(varchar,--oficina_id $1
							       varchar,--empresa_id $2
							       varchar,--almacen $3
							       varchar --ubicacion $4
							       )RETURNS SETOF pca_almacen.almacenes AS
$$
DECLARE
	_row pca_almacen.almacenes%ROWTYPE;
BEGIN
	FOR _row IN
		SELECT
			almacen,
			ubicacion,
			oficina_id,
			empresa_id
		FROM
			pca_almacen.almacenes
		WHERE
			oficina_id = $1 AND
			empresa_id = $2 AND
			lower(pca_global.fn_ascii(almacen)) = lower(pca_global.fn_ascii($3)) AND
			lower(pca_global.fn_ascii(ubicacion)) LIKE '%'|| lower(pca_global.fn_ascii($4)) ||'%'
		ORDER BY
			almacen ASC,
			ubicacion ASC
	LOOP
		RETURN NEXT _row;
	END LOOP;
END;
$$
LANGUAGE plpgsql;

-----------------------------------------------------------------------------------------------
---------------------------------- pca_almacen.inventario -------------------------------------
-----------------------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION pca_almacen.fn_add_all_articulos_to_invetario(integer,--tipo_articulo_id
									 varchar,--almacen $2
									 varchar,--ubicacion $3
									 varchar,--oficina_id $4
									 varchar,--empresa_id $5
									 bigint --sesion_id $6
									 )RETURNS void AS
$$
DECLARE
	_row pca_almacen.articulos%ROWTYPE;
	_almacen pca_almacen.inventario.almacen%TYPE;
	_ubicacion pca_almacen.inventario.ubicacion%TYPE;
	_oficina_id pca_almacen.inventario.oficina_id%TYPE;
	_empresa_id pca_almacen.inventario.empresa_id%TYPE;
	_sesion_id pca_almacen.inventario.sesion_id%TYPE;
	_medida_id pca_almacen.inventario.medida_id%TYPE;
	_stock_min pca_almacen.inventario.stock_min%TYPE;
	_stock_max pca_almacen.inventario.stock_max%TYPE;
	_stock_fin pca_almacen.inventario.stock_fin%TYPE;
	_moneda_id_costo pca_almacen.inventario.moneda_id_costo%TYPE;
	_incluye_igv_precio_costo pca_almacen.inventario.incluye_igv_precio_costo%TYPE;
	_precio_costo pca_almacen.inventario.precio_costo%TYPE;
	_moneda_id_venta pca_almacen.inventario.moneda_id_venta%TYPE;
	_incluye_igv_precio_venta pca_almacen.inventario.incluye_igv_precio_venta%TYPE;
	_precio_venta pca_almacen.inventario.precio_venta%TYPE;
BEGIN
	_almacen := $2;
	_ubicacion := $3;
	_oficina_id := $4;
	_empresa_id := $5;
	_sesion_id := $6;
	_medida_id := '01';
	_stock_min := 1;
	_stock_max := 100;
	_stock_fin := 1;
	_moneda_id_costo = pca.fn_get_moneda_default($4,$5);
	_incluye_igv_precio_costo = pca.fn_get_precios_inc_igv($4,$5);
	_precio_costo = 1;
	_moneda_id_venta = pca.fn_get_moneda_default($4,$5);
	_incluye_igv_precio_venta = pca.fn_get_precios_inc_igv($4,$5);
	_precio_venta = 1;

	FOR _row IN
		SELECT 
			articulo_id 
		FROM 
			pca_almacen.articulos 
		WHERE 
			tipo_articulo_id=0
		EXCEPT 
		SELECT 
			articulo_id 
		FROM 
			pca_almacen.inventario
		WHERE
			empresa_id = $5 AND
			oficina_id = $4
	LOOP
		EXECUTE pca_almacen.fn_add_inventario(_row.articulo_id,
						_almacen,
						_ubicacion,
						_oficina_id,
						_empresa_id,
						_sesion_id,
						_medida_id,
						_stock_min,
						_stock_max,
						_stock_fin,
						_moneda_id_costo,
						_incluye_igv_precio_costo,
						_precio_costo,
						_moneda_id_venta,
						_incluye_igv_precio_venta,
						_precio_venta);
	END LOOP;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_add_inventario(bigint,--articulo_id $1
							varchar,--almacen $2
							varchar,--ubicacion $3
							varchar,--oficina_id $4
							varchar,--empresa_id $5
							bigint,--sesion_id $6
							varchar,--medida_id $7
							numeric,--stock_min $8
							numeric,--stock_max $9
							numeric,--stock_fin $10
							varchar,--moneda_id_costo $11
							boolean,--incluye_igv_precio_costo $12
							numeric,--precio_costo $13
							varchar,--moneda_id_venta $14
							boolean,--incluye_igv_precio_venta $15
							numeric --precio_venta $16
							)RETURNS void AS
$$
BEGIN
	$2 = initcap(trim(both ' ' from $2));
	$3 = initcap(trim(both ' ' from $3));

	execute pca_almacen.fn_add_almacen($2,$3,$4,$5);

	INSERT INTO pca_almacen.inventario
		(articulo_id,--$1
		almacen,--$2
		ubicacion,--$3
		oficina_id,--$4
		empresa_id,--$5
		sesion_id,--$6
		medida_id,--$7
		stock_min,--$8
		stock_max,--$9
		stock_ini,--$10
		stock_fin,--$10
		moneda_id_costo,--$11
		incluye_igv_precio_costo,--$12
		precio_costo,--$13
		precio_costo_prom,--$13
		moneda_id_venta,--$14
		incluye_igv_precio_venta,--$15
		precio_venta)--$16
	VALUES
		($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$10,$11,$12,$13,$13,$14,$15,$16);
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_update_inventario(bigint,--articulo_id $1
							    varchar,--almacen $2
							    varchar,--ubicacion $3
							    varchar,--oficina_id $4
							    varchar,--empresa_id $5
							    bigint,--sesion_id $6
							    varchar,--medida_id $7
							    numeric,--stock_min $8
							    numeric,--stock_max $9
							    numeric,--stock_fin $10
							    varchar,--moneda_id_costo $11
							    boolean,--incluye_igv_precio_costo $12
							    numeric,--precio_costo $13
							    varchar,--moneda_id_venta $14
							    boolean,--incluye_igv_precio_venta $15
							    numeric --precio_venta $16
							    )RETURNS void AS
$$
BEGIN
	$2 = initcap(trim(both ' ' from $2));
	$3 = initcap(trim(both ' ' from $3));

	execute pca_almacen.fn_add_almacen($2,$3,$4,$5);

	UPDATE pca_almacen.inventario SET
		sesion_id=$6,
		medida_id=$7,
		stock_min=$8,
		stock_max=$9,
		stock_ini=$10,
		stock_fin=$10,
		stock_reservado=0,
		moneda_id_costo=$11,
		incluye_igv_precio_costo=$12,
		precio_costo=$13,
		precio_costo_prom=$13,
		moneda_id_venta=$14,
		incluye_igv_precio_venta=$15,
		precio_venta=$16
	WHERE
		articulo_id=$1 AND
		almacen=$2 AND
		ubicacion=$3 AND
		oficina_id=$4 AND
		empresa_id=$5;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_del_inventario(bigint,--articulo_id $1
							 varchar,--almacen $2
							 varchar,--ubicacion $3
							 varchar,--oficina_id $4
							 varchar --empresa_id $5
							 )RETURNS void AS
$$
BEGIN
	DELETE FROM
		pca_almacen.inventario
	WHERE
		articulo_id=$1 AND
		almacen=$2 AND
		ubicacion=$3 AND
		oficina_id=$4 AND
		empresa_id=$5;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_get_inventario(bigint,--articulo_id $1
							 varchar,--almacen $2
							 varchar,--ubicacion $3
							 varchar,--oficina_id $4
							 varchar --empresa_id $5
							 )RETURNS pca_almacen.vw_inventario AS
$$
DECLARE
	_row pca_almacen.vw_inventario%ROWTYPE;
BEGIN
	SELECT
		articulo_id,
		nombre_familia,
		nombre_sub_familia,
		nombre_marca,
		cod_interno,
		cod_barras,
		nombre_corto,
		descripcion,
		keywords,
		fecha_registro,
		activo,
		tipo_articulo_id,
		almacen,
		ubicacion,
		oficina_id,
		empresa_id,
		sesion_id,
		medida_id,
		stock_min,
		stock_max,
		stock_ini,
		stock_fin,
		stock_reservado,
		moneda_id_costo,
		moneda_costo,
		moneda_siglas_costo,
		incluye_igv_precio_costo,
		precio_costo,
		precio_costo_prom,
		moneda_id_venta,
		moneda_venta,
		moneda_siglas_venta,
		incluye_igv_precio_venta,
		precio_venta
	INTO
		_row
	FROM
		pca_almacen.vw_inventario
	WHERE
		articulo_id=$1 AND
		almacen=$2 AND
		ubicacion=$3 AND
		oficina_id=$4 AND
		empresa_id=$5;

	RETURN _row;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_get_list_inventario(integer,--start $1
							      integer,--limit $2
							      varchar,--oficina_id $3
							      varchar,--empresa_id $4
							      integer --tipo_articulo_id $5
							      )RETURNS SETOF refcursor AS
$$
DECLARE
	cursor_result refcursor;
	cursor_totalrows refcursor;
BEGIN
	OPEN cursor_result FOR
		SELECT
			articulo_id,
			nombre_familia,
			nombre_sub_familia,
			nombre_marca,
			cod_interno,
			cod_barras,
			nombre_corto,
			descripcion,
			keywords,
			fecha_registro,
			activo,
			tipo_articulo_id,
			almacen,
			ubicacion,
			oficina_id,
			empresa_id,
			sesion_id,
			medida_id,
			stock_min,
			stock_max,
			stock_ini,
			stock_fin,
			stock_reservado,
			moneda_id_costo,
			moneda_costo,
			moneda_siglas_costo,
			incluye_igv_precio_costo,
			precio_costo,
			precio_costo_prom,
			moneda_id_venta,
			moneda_venta,
			moneda_siglas_venta,
			incluye_igv_precio_venta,
			precio_venta
		FROM
			pca_almacen.vw_inventario
		WHERE
			oficina_id=$3 AND
			empresa_id=$4 AND
			tipo_articulo_id=$5
		ORDER BY
			fecha_registro ASC LIMIT $2 OFFSET $1;
	RETURN NEXT cursor_result;

	OPEN cursor_totalrows FOR
		SELECT
			count(articulo_id)
		FROM
			pca_almacen.vw_inventario
		WHERE
			oficina_id = $3 AND
			empresa_id = $4 AND
			tipo_articulo_id = $5;
	RETURN NEXT cursor_totalrows;	
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_get_list_inventario(integer,--start $1
							      integer,--limit $2
							      varchar,--oficina_id $3
							      varchar,--empresa_id $4
							      integer,--tipo_articulo_id $5
							      varchar --nombre corto | cod_interno $6
							      )RETURNS SETOF refcursor AS
$$
DECLARE
	cursor_result refcursor;
	cursor_totalrows refcursor;
BEGIN
	OPEN cursor_result FOR
		SELECT
			articulo_id,
			nombre_familia,
			nombre_sub_familia,
			nombre_marca,
			cod_interno,
			cod_barras,
			nombre_corto,
			descripcion,
			keywords,
			fecha_registro,
			activo,
			tipo_articulo_id,
			almacen,
			ubicacion,
			oficina_id,
			empresa_id,
			sesion_id,
			medida_id,
			stock_min,
			stock_max,
			stock_ini,
			stock_fin,
			stock_reservado,
			moneda_id_costo,
			moneda_costo,
			moneda_siglas_costo,
			incluye_igv_precio_costo,
			precio_costo,
			precio_costo_prom,
			moneda_id_venta,
			moneda_venta,
			moneda_siglas_venta,
			incluye_igv_precio_venta,
			precio_venta
		FROM
			pca_almacen.vw_inventario
		WHERE
			oficina_id = $3 AND
			empresa_id = $4 AND
			tipo_articulo_id = $5 AND
			(lower(pca_global.fn_ascii(nombre_corto)) LIKE '%'|| lower(pca_global.fn_ascii($6)) ||'%' OR
			lower(pca_global.fn_ascii(cod_interno)) LIKE '%'|| lower(pca_global.fn_ascii($6)) ||'%')
		ORDER BY
			fecha_registro ASC LIMIT $2 OFFSET $1;
	RETURN NEXT cursor_result;

	OPEN cursor_totalrows FOR
		SELECT
			count(articulo_id)
		FROM
			pca_almacen.vw_inventario
		WHERE
			oficina_id = $3 AND
			empresa_id = $4 AND
			tipo_articulo_id = $5 AND
			(lower(pca_global.fn_ascii(nombre_corto)) LIKE '%'|| lower(pca_global.fn_ascii($6)) ||'%' OR
			lower(pca_global.fn_ascii(cod_interno)) LIKE '%'|| lower(pca_global.fn_ascii($6)) ||'%');
	RETURN NEXT cursor_totalrows;	
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_get_list_inventario(integer,--start $1
							      integer,--limit $2
							      varchar,--oficina_id $3
							      varchar,--empresa_id $4
							      varchar --nombre corto | cod_interno $5
							      )RETURNS SETOF refcursor AS
$$
DECLARE
	cursor_result refcursor;
	cursor_totalrows refcursor;
BEGIN
	OPEN cursor_result FOR
		SELECT
			articulo_id,
			nombre_familia,
			nombre_sub_familia,
			nombre_marca,
			cod_interno,
			cod_barras,
			nombre_corto,
			descripcion,
			keywords,
			fecha_registro,
			activo,
			tipo_articulo_id,
			almacen,
			ubicacion,
			oficina_id,
			empresa_id,
			sesion_id,
			medida_id,
			stock_min,
			stock_max,
			stock_ini,
			stock_fin,
			stock_reservado,
			moneda_id_costo,
			moneda_costo,
			moneda_siglas_costo,
			incluye_igv_precio_costo,
			precio_costo,
			precio_costo_prom,
			moneda_id_venta,
			moneda_venta,
			moneda_siglas_venta,
			incluye_igv_precio_venta,
			precio_venta
		FROM
			pca_almacen.vw_inventario
		WHERE
			oficina_id=$3 AND
			empresa_id=$4 AND
			(lower(pca_global.fn_ascii(nombre_corto)) LIKE '%'|| lower(pca_global.fn_ascii($5)) ||'%' OR
			lower(pca_global.fn_ascii(cod_interno)) LIKE '%'|| lower(pca_global.fn_ascii($5)) ||'%')
		ORDER BY
			fecha_registro ASC LIMIT $2 OFFSET $1;
	RETURN NEXT cursor_result;

	OPEN cursor_totalrows FOR
		SELECT
			count(articulo_id)
		FROM
			pca_almacen.vw_inventario
		WHERE
			oficina_id=$3 AND
			empresa_id=$4 AND
			(lower(pca_global.fn_ascii(nombre_corto)) LIKE '%'|| lower(pca_global.fn_ascii($5)) ||'%' OR
			lower(pca_global.fn_ascii(cod_interno)) LIKE '%'|| lower(pca_global.fn_ascii($5)) ||'%');
	RETURN NEXT cursor_totalrows;	
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_almacen.fn_get_list_inventario(integer,--start $1
							      integer, --limit $2
							      varchar,--oficina_id $3
							      varchar,--empresa_id $4
							      integer,--tipo_articulo_id $5
							      varchar[] --filtros $6
							      )RETURNS SETOF refcursor AS
$$
DECLARE
	cursor_result refcursor;
	cursor_totalrows refcursor;
	sqlfiltro varchar;
	sqlcount varchar;
BEGIN
	$6 := $6 || ARRAY[['string','eq',$3,'oficina_id'],['string','eq',$4,'empresa_id'],['numeric','eq',$5::varchar,'tipo_articulo_id']];
	
	sqlfiltro := 
		'SELECT
			articulo_id,
			nombre_familia,
			nombre_sub_familia,
			nombre_marca,
			cod_interno,
			cod_barras,
			nombre_corto,
			descripcion,
			keywords,
			fecha_registro,
			activo,
			tipo_articulo_id,
			almacen,
			ubicacion,
			oficina_id,
			empresa_id,
			sesion_id,
			medida_id,
			stock_min,
			stock_max,
			stock_ini,
			stock_fin,
			stock_reservado,
			moneda_id_costo,
			moneda_costo,
			moneda_siglas_costo,
			incluye_igv_precio_costo,
			precio_costo,
			precio_costo_prom,
			moneda_id_venta,
			moneda_venta,
			moneda_siglas_venta,
			incluye_igv_precio_venta,
			precio_venta
		FROM
			pca_almacen.vw_inventario
		WHERE '|| 
			pca_global.fn_get_strfiltro($6)|| 
		' ORDER BY
			fecha_registro ASC LIMIT '|| $2 || ' OFFSET '|| $1 ;

	sqlcount := 
		'SELECT
			count(articulo_id)
		FROM
			pca_almacen.vw_inventario
		WHERE '|| 
			pca_global.fn_get_strfiltro($6);
	
	OPEN cursor_result FOR
		EXECUTE(sqlfiltro);
	RETURN NEXT cursor_result;

	OPEN cursor_totalrows FOR
		EXECUTE(sqlcount);
	RETURN NEXT cursor_totalrows;	
END;
$$
LANGUAGE plpgsql;